package com.sxr.signature;

import com.sxr.signature.util.UrlUtil;

import java.util.Map;
import java.util.TreeMap;

/**
 * 签名请求参数
 *
 * @author SXR
 * @since 1.0.0
 */
public class SignRequest {
    /** 租户ID */
    private String tenantId;

    /** 文件路径 */
    private String filePath;

    /** 过期时间戳(毫秒) */
    private Long expireTime;

    /** 访问次数限制 */
    private Integer accessLimit;

    /** 是否为预览模式 */
    private Boolean preview;

    /** 客户端IP - 仅用于日志记录，不参与签名计算 */
    private String clientIp;

    /** 扩展参数 */
    private Map<String, String> extraParams;

    /** 签名密钥 */
    private String secretKey;

    public SignRequest() {
    }

    public SignRequest(String tenantId, String filePath) {
        this.tenantId = tenantId;
        this.filePath = filePath;
    }


    /**
     * 构建安全URL
     *
     * @param baseUrl 基础的url : http://java.com/download/
     * @param signature 签名之后的内容 : 需要用私钥加密之后.
     * @return
     */
    public final String buildSecureUrl(String baseUrl,String signature) {
        StringBuilder urlBuilder = new StringBuilder(baseUrl);

        // 租户ID
        if (this.getTenantId() != null) {
            urlBuilder.append(this.getTenantId()).append("/");
        }

        // 文件路径
        urlBuilder.append(this.getFilePath());

        // 查询参数 - 对签名进行URL编码
        urlBuilder.append("?signature=").append(UrlUtil.urlEncode(signature));

        if (this.getExpireTime() != null) {
            urlBuilder.append("&expire=").append(this.getExpireTime());
        }

        if (this.getAccessLimit() != null) {
            urlBuilder.append("&limit=").append(this.getAccessLimit());
        }

        // 添加extraParams到URL中
        if (this.getExtraParams() != null && !this.getExtraParams().isEmpty()) {
            for (Map.Entry<String, String> entry : this.getExtraParams().entrySet()) {
                urlBuilder.append("&").append(UrlUtil.urlEncode(entry.getKey()))
                        .append("=").append(UrlUtil.urlEncode(entry.getValue()));
            }
        }

        return urlBuilder.toString();
    }

    /**
     * 构建待签名字符串
     * 按照参数名字典序排列，确保(加密/解密)签名一致性
     */
    public final String buildStringToSign() {
        TreeMap<String, String> params = new TreeMap<>();

        // 添加基础参数
        if (this.getTenantId() != null) {
            params.put("tenantId", this.getTenantId());
        }
        if (this.getFilePath() != null) {
            String filePath = UrlUtil.urlDecode(this.getFilePath());
            params.put("filePath", filePath);
        }
        if (this.getExpireTime() != null) {
            params.put("expireTime", this.getExpireTime().toString());
        }
        if (this.getAccessLimit() != null) {
            params.put("accessLimit", this.getAccessLimit().toString());
        }
        // 注意：preview参数不参与签名计算，使同一个签名可以用于预览和下载
        // 注意：clientIp不参与签名计算，避免用户切换网络时签名失效

        // 添加扩展参数
        if (this.getExtraParams() != null) {
            params.putAll(this.getExtraParams());
        }

        // 构建签名字符串
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (stringBuilder.length() > 0) {
                stringBuilder.append("&");
            }
            stringBuilder.append(entry.getKey()).append("=").append(entry.getValue());
        }

        return stringBuilder.toString();
    }

    // Getter and Setter methods
    public String getTenantId() {
        return tenantId;
    }

    public void setTenantId(String tenantId) {
        this.tenantId = tenantId;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public Long getExpireTime() {
        return expireTime;
    }

    public void setExpireTime(Long expireTime) {
        this.expireTime = expireTime;
    }

    public Integer getAccessLimit() {
        return accessLimit;
    }

    public void setAccessLimit(Integer accessLimit) {
        this.accessLimit = accessLimit;
    }

    public Boolean getPreview() {
        return preview;
    }

    public void setPreview(Boolean preview) {
        this.preview = preview;
    }

    public String getClientIp() {
        return clientIp;
    }

    public void setClientIp(String clientIp) {
        this.clientIp = clientIp;
    }

    public Map<String, String> getExtraParams() {
        return extraParams;
    }

    public void setExtraParams(Map<String, String> extraParams) {
        this.extraParams = extraParams;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    @Override
    public String toString() {
        return "SignRequest{" +
                "tenantId='" + tenantId + '\'' +
                ", filePath='" + filePath + '\'' +
                ", expireTime=" + expireTime +
                ", accessLimit=" + accessLimit +
                ", clientIp='" + clientIp + '\'' +
                ", extraParams=" + extraParams +
                ", secretKey='***'" +
                '}';
    }
}
